#ifndef TRANSFORMERCONTENTGETINFOFROMSTACK_HPP_3
#define TRANSFORMERCONTENTGETINFOFROMSTACK_HPP_3

#include "logger.hpp"
#include "transContentDefine.h"
#include "transContentErrorCode.h"
#include "transContentDispatcher.hpp"
#include "transContentSetting.hpp"

class TransContentGetStackInfo{
	/////////////////////////////////////////////////////
	/// get local address
	///		just send get local packet request, not need wait response
	///
	///		name | length | mainCode | subCode |
	///		len  |    2   |    1     |    1    |
	///   offset |    0   |    2     |    3    |
	/// return:
	///		E_TRANC_SUCESS: operation sucessfully
	/////////////////////////////////////////////////////
	static int getStackLocalAddr(){
		char buffer[8]={1};
		*(short*(buffer)) = 4;
		debug_enter();
		buffer[2] = (char)message_type_inner_getStackInfo;
		buffer[3] = (char)message_type_stackInfo_sub_getLocalAddr;
		logd_info("begin to send data to stack");
		TransContentDispatcher::getInstance()->sendDataRegistToStack(buffer, 4);
		debug_leave();
		return E_TRANC_SUCESS;
	}

	//////////////////////////////////////////////////////////////////////////////////////////
	/// set fixed path to stack
	///		no block method, just send packet to stack and return, not need wait response
	///
	///		packet content format
	///		name | length | maincode | subCode | target | nodeCount | nodes |
	///		len  |   2    |    1     |    1    |    8   |    2      |   xx  |
	///   offset |   0    |    2     |    3    |    4   |    12     |   14  |
	/// parameters:
	///		target: set fixed path to target
	///		nodeList: the node path to target
	///		nodeCount: the nodeList size
	///
	/// return:
	///		E_TRANC_SUCESS: operation finished
	//////////////////////////////////////////////////////////////////////////////////////////
	static int setFixedPath(const NodeAddr* target, const NodeAddr* nodeList, int nodeCount){
		int length = sizeof(NodeAddr) * nodeCount;
		char* buffer = NULL;
		debug_enter();
		length += 14;
		buffer = (char*)calloc(length, 1);
		logd_info("begin to set packet content");
		*(short*(buffer)) = 14;
		buffer[2] = (char)message_type_inner_getStackInfo;
		buffer[3] = (char)message_type_stackInfo_sub_setFixedPath;
		*(NodeAddr*(buffer+4)) = *target;
		*(short*(buffer+12)) = (short)nodeCount;
		memcpy(buffer+14, nodeList, nodeCount*sizeof(NodeAddr));
		logd_info("start send data to stack");
		TransContentDispatcher::getInstance()->sendDataRegistToStack(buffer, length);
		free(buffer);
		logd_leave();
		return E_TRANC_SUCESS;
	}

	//////////////////////////////////////////////////////////////////////////////////
	/// stack info response
	///		get subMessage code to get detail dispatcher
	///
	///		packet content format header
	///		name | mainCode | subCode |
	///		len  |    1     |   1     |
	///   offset |    0     |   1     |
	///
	/// parameters:
	///		buffer: the response content
	///		index: the buffer index in memory pool
	///
	/// return:
	///		RESPONSE_RESULT_NOACTION: since the protocol not use localPort, so do nothing
	//////////////////////////////////////////////////////////////////////////////////
	static int response(char* buffer, int index){
		int subCode = buffer[1];
		debug_enter();
		switch(subCode){
			case message_type_stackInfo_sub_getLocalAddr:
				logd_info("sub message get local address");
				stackResponse_LocalAddr(buffer);
				break;
			default:
				logd_error("get stack info response, not support the sub message: %d", subCode);
		}
		TransContentMemory::getInstance()->releaseBuffer(index);
		debug_leave();
		return RESPONSE_RESULT_NOACTION;
	}

	private:
	/////////////////////////////////////////////////////////////////////////////////////
	/// get local address detail response
	///
	///		name | mainCode | subCode | localAddr |
	///      len |    1     |    1    |    8      |
	///    offset|    0     |    1    |    2      |
	///
	/// parameter:
	///		buffer: the response buffer
	//////////////////////////////////////////////////////////////////////////////////////
	void stackResponse_LocalAddr(char* buffer){
		debug_enter();
		NodeAddr tempAddr = *(NodeAddr*(buffer+2));
		TransContentSetting::setLocalAddr(&tempAddr);
		logd_info("set local address to %lld", tempAddr.serial_id);
		debug_leave();
		return;
	}
};
#endif //TRANSFORMERCONTENTGETINFOFROMSTACK_HPP_3
